import re

from PIL import Image
from django import forms
from django.contrib.auth import authenticate
from django.contrib.auth.hashers import check_password
from django.core.files.uploadedfile import InMemoryUploadedFile

from my_apps.videos.models import VideoSub, Video
from .models import UserProfile, UserFavorite
from utils.cut_image import cut_image


class Reform(forms.Form):
    """用户名验证注册"""
    username = forms.CharField(required=True)
    password = forms.CharField(required=True)
    check_password = forms.CharField(required=True)

    def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')
        check_password = self.cleaned_data.get('check_password')

        if not username or not password or not check_password:
            raise forms.ValidationError('请填写完整!')

        if not re.match(r'^[-_a-zA-Z0-9]{8,16}$', str(username)):
            raise forms.ValidationError('用户ID不合法')

        if not re.match(r'(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[$@!%*#?&.])[A-Za-z\d$@!%*#?&.]{8,16}$', password):
            raise forms.ValidationError('密码不合法')

        if password != check_password:
            raise forms.ValidationError('两次密码不一致')

        user = UserProfile.objects.filter(username=username)
        if user:
            raise forms.ValidationError('账户ID已存在')
        return self.cleaned_data


class SendEmailForm(forms.Form):
    """邮箱验证注册"""
    email = forms.EmailField(required=True)
    password = forms.CharField(required=True)
    check_password = forms.CharField(required=True, )

    def clean(self):
        email = self.cleaned_data.get('email')
        password = self.cleaned_data.get('password')
        check_password = self.cleaned_data.get('check_password')

        if not email or not password or not check_password:
            raise forms.ValidationError('请填写完整!')

        if not re.match(r'^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$', str(email)):
            raise forms.ValidationError('邮箱不合法')

        if not re.match(r'(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[$@!%*#?&.])[A-Za-z\d$@!%*#?&.]{8,16}$', password):
            raise forms.ValidationError('密码不合法')

        if password != check_password:
            raise forms.ValidationError('两次密码不一致')

        user = UserProfile.objects.filter(email=email)
        if user:
            raise forms.ValidationError('邮箱已被注册')
        return self.cleaned_data


class CheckEmailForm(forms.Form):
    """邮箱验证"""
    email = forms.EmailField()

    def clean(self):
        email = self.cleaned_data.get('email')
        if not email:
            raise forms.ValidationError('请输入邮箱')
        if not re.match(r'^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$', email):
            raise forms.ValidationError('请输入正确的邮箱')
        return self.cleaned_data


class LoginForm(forms.Form):
    """登录验证注册"""
    username = forms.CharField(required=True, error_messages={
        'required': '输入用户名或邮箱'
    })
    password = forms.CharField(required=True, error_messages={
        'required': '输入密码'
    })

    def clean(self):
        username = self.cleaned_data.get('username')
        password = self.cleaned_data.get('password')

        # 验证是否输入
        if not username or not password:
            raise forms.ValidationError('输入用户名或密码')

        #  邮箱验证登录  验证是否符合邮箱
        if re.search(r'[0-9a-zA-Z_]{0,19}@[0-9a-zA-Z]{1,13}\.[com,cn,net]{1,3}', str(username)):

            #  用户邮箱 查找
            all_user = UserProfile.objects.filter(email=username)
            for user in all_user:
                if not user:
                    raise forms.ValidationError('用户不存在')

                if not check_password(password, user.password):
                    raise forms.ValidationError('用户名或密码错误')

                self.cleaned_data['user'] = user
                return self.cleaned_data

        #  用户名验证登录 区分大小写contains
        user = UserProfile.objects.filter(username__contains=username)
        if not user:
            raise forms.ValidationError('用户不存在')

        user = authenticate(username=username, password=password)
        if not user:
            raise forms.ValidationError('用户名或密码错误')
        self.cleaned_data['user'] = user
        return self.cleaned_data


class ChangePasswordForm(forms.Form):
    """更换密码"""
    old_password = forms.CharField(required=True)
    new_password = forms.CharField(required=True)
    new_check_password = forms.CharField(required=True)

    def __init__(self, request):
        self.request = request
        super().__init__(request.POST)

    def clean(self):
        old_password = self.cleaned_data.get('old_password')
        new_password = self.cleaned_data.get('new_password')
        new_check_password = self.cleaned_data.get('new_check_password')

        if not old_password or not new_check_password or not new_password:
            raise forms.ValidationError('请填写完整!')

        # 比对输入的old_pwd与数据库中的密码
        if not check_password(old_password, self.request.user.password):
            raise forms.ValidationError('旧密码与原密码不一致')

        if not re.match(r'(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[$@!%*#?&.])[A-Za-z\d$@!%*#?&.]{8,16}$', new_password):
            raise forms.ValidationError('新密码不合法')

        if new_password == old_password:
            raise forms.ValidationError('新密码不能与旧密码一致')

        if new_password != new_check_password:
            raise forms.ValidationError('两次密码不一致')

        return self.cleaned_data


class ForgetPwdForm(forms.Form):
    """重新设定密码"""
    new_password = forms.CharField(required=True)
    new_check_password = forms.CharField(required=True)

    def clean(self):
        new_password = self.cleaned_data.get('new_password')
        new_check_password = self.cleaned_data.get('new_check_password')

        if not new_check_password or not new_password:
            raise forms.ValidationError('请填写完整!')

        if not re.match(r'(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[$@!%*#?&.])[A-Za-z\d$@!%*#?&.]{8,16}$', new_password):
            raise forms.ValidationError('新密码不合法')

        if new_password != new_check_password:
            raise forms.ValidationError('两次密码不一致')

        return self.cleaned_data


class RealNameAuthenticationForm(forms.Form):
    """实名认真表单验证"""
    real_name = forms.CharField(required=True)
    identify_card = forms.CharField(required=True)

    def clean(self):
        real_name = self.cleaned_data.get('real_name')
        identify_card = self.cleaned_data.get('identify_card')

        if not real_name:
            raise forms.ValidationError('请输入姓名')

        if not identify_card:
            raise forms.ValidationError('请输入身份证号')

        if not re.match(r'^[\u4e00-\u9fa5]{0,}$', real_name):
            raise forms.ValidationError('姓名不合法')

        if not re.match(r'^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$',
                        identify_card) and not \
                re.match(r'^[1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$', identify_card):
            raise forms.ValidationError('身份证不合法')

        return self.cleaned_data


class AddFavForm(forms.ModelForm):
    class Meta:
        model = UserFavorite
        fields = ['fav_id', 'fav_type']


class ChangePicForm(forms.ModelForm):
    """处理上传的头像"""
    class Meta:
        model = UserProfile
        fields = ['image']

    def clean_image(self):
        img = self.cleaned_data.get('image')
        x = self.data.get('x')
        y = self.data.get('y')
        x2 = self.data.get('x2')
        y2 = self.data.get('y2')
        iw = self.data.get('iw')[:-2]  # 去px
        if type(img) == str:
            raise forms.ValidationError('请选择一张图片')
        if not x or not y or not x2 or not y2 or not iw:
            raise forms.ValidationError('参数错误')
        # 处理图片 image 可以直接打开file对象 InMemoryUploadedFile
        # 修改图片尺寸
        file = cut_image(img, int(iw), int(x), int(y), int(x2), int(y2))
        return file


class ChangeInfoForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ['nick_name', 'birthday', 'gender', 'address']


class VideoUploadForm(forms.ModelForm):
    class Meta:
        model = VideoSub
        fields = ['user_field']


class VideoForm(forms.ModelForm):
    class Meta:
        model = Video
        fields = ['name', 'image', 'info']
